#ifndef __MY__MANAGER__
#define __MY__MANAGER__
#include <unordered_map>
#include <pthread.h>
#include "Util.hpp"
#include "Config.hpp"




namespace Cloude
{
	using std::string;
	using std::cout;
	using std::endl;
	using std::vector;
	struct BackupInfo
	{
		// 用于热点管理
		time_t _hot_time;
		// 用于页面展示
		time_t _atime;
		time_t _mtime;
		size_t _filesz;
		// _back_path 是默认的实际存储路径
		// 也是实际的存储路径
		// ./back_dir/a.txt
		string _back_path;
		// 只有在热点管理中，才会将更改为pack_path
		// ./pack_dir/a,txt.lz
		string _pack_path;
		// 压缩标志 --> 决定了备份文件的存储位置 是 _back_path or _pack_path
		// 下::载请求 /download/a.txt 作为key, 用来搜索曾经备份文件的信息，所以用哈希存储
		string _url;
		string _url_prefix;
		bool _pack_flag;
		string _filename;

		BackupInfo()
		{}

		// 需要思考什么时候才需要 创建备份信息？ 只有请求为上传文件请求时
		// 你需要创建备份信息结构体，填充内部字段，并加入哈希表内
		// 是能够保证 realpath 是真实的 ./back_dir/ 路径
		bool NewBackupInfo(const string& backpath)
		{
			// 填充字段
			// ./back_dir/a.txt
			Cloude::FileUtil fu(backpath);
			if(fu.IsExist() == false)
			{
				cout << "DataManager::NewBackupInfo failed..." << endl;
				return false;
			}
			_atime = fu.GetFileSize();
			_atime = fu.GetATime();
			_mtime = fu.GetMTime();
			_filesz = fu.GetFileSize();
			// a.txt
			_filename = fu.FileName();
			Cloude::Config* config = Cloude::Config::GetInstance();
			_hot_time = config->GetHTime();
			//./back_dir/a.txt
			_back_path = backpath;
			//./pack_dir/a.txt.lz
			_pack_path = config->GetPackDir() + _filename + config->GetPackSuff();
			_url = config->GetUrlPre() + _filename;
			_url_prefix = config->GetUrlPre();
			_pack_flag = false;
		
		
		}

		void Print()
		{
			cout << _hot_time << endl;
			cout << _atime << endl;
			cout << _mtime << endl;
			cout << _filesz << endl;
			cout << _back_path << endl;
			cout << _pack_path << endl;
			cout << _url << endl;
			cout << _url_prefix << endl;
		}
	};

	/*
		这个数据管理模块--DataManager,一定是多线程访问的。
		注定要保护共享资源,这里使用读写锁,因为读共享写互斥,
		可以大大提高效率
	*/

	class DataManager
	{
	private:
		// 所有的备份文件的信息存放在 ./back.dat中
		string _mdata_file;
		std::unordered_map<string,BackupInfo> _table;
		pthread_rwlock_t _rwlock;
	public:
		DataManager()
		{
		    _mdata_file = Cloude::Config::GetInstance()->GetMFile();
			pthread_rwlock_init(&_rwlock,nullptr);
			Load();
		}

		~DataManager()
		{
			Store();
			pthread_rwlock_destroy(&_rwlock);
		}

		// 加载备份文件的信息
		void Load()
		{
			Cloude::FileUtil fu(_mdata_file);
			if(fu.IsExist() == false)
			{
				return;
			}
			// 获取数据 加锁保护
			string str;
			pthread_rwlock_rdlock(&_rwlock);

			if (fu.GetContent(&str) == false)
			{
				cout << "DataManager::Load failed.." << endl;
				pthread_rwlock_unlock(&_rwlock);
				return;
			}
			pthread_rwlock_unlock(&_rwlock);

			//反序列化
			Json::Value root;
			Cloude::JsonUtil::DisSerialize(str,&root);
			for(int i = 0; i < root.size(); i++)
			{
				BackupInfo info;
				info._hot_time = root[i]["hot_time"].asInt64();
				info._atime = root[i]["atime"].asInt64();
				info._mtime = root[i]["mtime"].asInt64();
				info._filesz = root[i]["filesz"].asUInt();
				info._back_path = root[i]["back_path"].asString();
				info._pack_path = root[i]["pack_path"].asString();
				info._pack_flag = root[i]["pack_flag"].asBool();
				info._url = root[i]["url"].asString();
			    info._filename = root[i]["filename"].asString() ;
				// 加载到内存中
				_table[info._url] = info;
			}

		}

		// 存储备份文件的信息 
		void Store()
		{
			vector<BackupInfo> arry;
			GetAll(&arry);
			// 以Json格式存储
			Json::Value root;
			for(int i = 0; i < arry.size(); i++)
			{
				Json::Value item;
				item["hot_time"] = static_cast<Json::Int64>(arry[i]._hot_time);
				item["back_path"] = arry[i]._back_path;
				item["pack_path"] = arry[i]._pack_path;
				item["url_prefix"] = arry[i]._url_prefix;
				item["url"] = arry[i]._url;
				item["atime"] = static_cast<Json::Int64>(arry[i]._atime);
				item["mtime"] = static_cast<Json::Int64>(arry[i]._mtime);
				item["filesz"] = static_cast<Json::UInt>(arry[i]._filesz);
				item["pack_flag"] = arry[i]._pack_flag;
				item["filename"] = arry[i]._filename;
				root.append(item);
			}

			// 序列化
			string str;
			Cloude::JsonUtil::Serialize(&str,root);
			// 保存 --要 加锁保护
			pthread_rwlock_wrlock(&_rwlock);
			
			Cloude::FileUtil fu(_mdata_file);
			if (fu.SetContent(str) == false)
			{
				cout << "DataManager::Store failed.." << endl;
				pthread_rwlock_unlock(&_rwlock);
				return;
			}

			pthread_rwlock_unlock(&_rwlock);
		
		}
		
		bool Insert(const BackupInfo& info)
		{
			pthread_rwlock_wrlock(&_rwlock);
			_table[info._url] = info;
			pthread_rwlock_unlock(&_rwlock);

			Store();
			return true;
		}

		bool Update(const BackupInfo& info)
		{
			pthread_rwlock_wrlock(&_rwlock);
			_table[info._url] = info;
			pthread_rwlock_unlock(&_rwlock);

			Store();
			return true;

		}
		// 获取所有的备份文件的信息 
		bool GetAll(vector<BackupInfo>* arry)
		{
			//加锁保护
			pthread_rwlock_rdlock(&_rwlock);
			
			for(auto& [k,v] : _table)
			{
				arry->push_back(v);
			}
			
			pthread_rwlock_unlock(&_rwlock);
			return true;
		}

		bool GetOneByUrl(const string& url,BackupInfo* info)
		{
			pthread_rwlock_rdlock(&_rwlock);

			if(_table.count(url) == 0)
			{
				pthread_rwlock_unlock(&_rwlock);
				return false;
			}
			*info = _table[url];
		
			pthread_rwlock_unlock(&_rwlock);
			return true;
		}

		bool GetOneByRealPath(const string& back_path,BackupInfo* info)
		{
			pthread_rwlock_rdlock(&_rwlock);
			for(auto& [k,v] : _table)
			{
				if(v._back_path == back_path)
				{
					*info = v;
					pthread_rwlock_unlock(&_rwlock);
					return true;
				}
			}
			pthread_rwlock_unlock(&_rwlock);
			return false;
		}
	};
}

#endif
